package com.ruoyi.web.controller.merchant;

import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.TokenService;  // ← 添加 TokenService
import com.ruoyi.merchant.domain.Merchant;
import com.ruoyi.merchant.domain.dto.MerchantLoginRequest;
import com.ruoyi.merchant.domain.dto.MerchantRegisterRequest;
import com.ruoyi.merchant.mapper.MerchantMapper;  // ← 添加 Mapper
import com.ruoyi.merchant.service.IMerchantAuthService;
import com.ruoyi.service.SmsService;
import com.ruoyi.system.mapper.SysUserMapper;  // ← 添加 Mapper
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * 商家认证Controller（登录、注册）
 */
@RestController
@RequestMapping("/merchant/auth")
@Slf4j
public class MerchantAuthController {

    @Autowired
    private IMerchantAuthService merchantAuthService;

    @Autowired
    private SysLoginService loginService;

    @Autowired
    private TokenService tokenService;  // ← 添加 TokenService

    @Autowired
    private MerchantMapper merchantMapper;  // ← 添加 MerchantMapper

    @Autowired
    private SysUserMapper userMapper;  // ← 添加 SysUserMapper

    @Autowired
    private SmsService smsService;

    @Autowired
    private RedisCache redisCache;

    // 短信验证码缓存键前缀
    private static final String SMS_CODE_KEY = "sms_code:";

    /**
     * 商家注册
     */
    @PostMapping("/register")
    public AjaxResult register(@RequestBody MerchantRegisterRequest request) {
        try {
            log.info("商家注册请求，手机号: {}", request.getPhone());

            // 1. 参数校验
            if (StringUtils.isEmpty(request.getPhone())) {
                return AjaxResult.error("手机号不能为空");
            }
            if (StringUtils.isEmpty(request.getPassword())) {
                return AjaxResult.error("密码不能为空");
            }
            if (StringUtils.isEmpty(request.getConfirmPassword())) {
                return AjaxResult.error("确认密码不能为空");
            }
            if (StringUtils.isEmpty(request.getSmsCode())) {
                return AjaxResult.error("验证码不能为空");
            }

            // 2. 验证手机号格式
            if (!request.getPhone().matches("^1[3-9]\\d{9}$")) {
                return AjaxResult.error("手机号格式不正确");
            }

            // 3. 密码长度校验
            if (request.getPassword().length() < 6) {
                return AjaxResult.error("密码长度不能少于6位");
            }

            // 4. 密码确认验证
            if (!request.getPassword().equals(request.getConfirmPassword())) {
                return AjaxResult.error("两次输入的密码不一致");
            }

            // 5. 验证码验证
            String cacheKey = SMS_CODE_KEY + request.getPhone();
            String cachedCode = redisCache.getCacheObject(cacheKey);

            if (StringUtils.isEmpty(cachedCode)) {
                return AjaxResult.error("验证码已过期，请重新获取");
            }

            if (!cachedCode.equals(request.getSmsCode())) {
                return AjaxResult.error("验证码错误");
            }

            // 6. 验证通过，删除缓存中的验证码
            redisCache.deleteObject(cacheKey);

            // 7. 调用Service执行注册
            AjaxResult result = merchantAuthService.register(request);

            log.info("商家注册成功，手机号: {}", request.getPhone());
            return result;

        } catch (Exception e) {
            log.error("商家注册失败，手机号: " + request.getPhone(), e);
            return AjaxResult.error(e.getMessage());
        }
    }

    /**
     * 商家登录
     */
    @PostMapping("/login")
    public AjaxResult login(@RequestBody MerchantLoginRequest request) {
        try {
            log.info("商家登录请求，手机号: {}, 登录方式: {}",
                    request.getPhone(), request.getLoginType());

            // 1. 参数校验
            if (StringUtils.isEmpty(request.getPhone())) {
                return AjaxResult.error("手机号不能为空");
            }

            // 2. 验证手机号格式
            if (!request.getPhone().matches("^1[3-9]\\d{9}$")) {
                return AjaxResult.error("手机号格式不正确");
            }

            String token = null;

            // 3. 根据登录方式处理
            if ("password".equals(request.getLoginType())) {
                // ==================== 密码登录 ====================
                if (StringUtils.isEmpty(request.getPassword())) {
                    return AjaxResult.error("密码不能为空");
                }

                // 验证商家信息
                AjaxResult merchantResult = merchantAuthService.login(request);
                if (merchantResult.get("code").equals(500)) {
                    return merchantResult;
                }

                // 使用若依的登录服务生成token（会验证密码）
                token = loginService.login(
                        request.getPhone(),
                        request.getPassword(),
                        null,
                        null
                );

                // 构造返回结果
                AjaxResult ajax = AjaxResult.success("登录成功");
                ajax.put(Constants.TOKEN, token);
                ajax.put("merchantInfo", merchantResult.get("data"));

                log.info("商家密码登录成功，手机号: {}", request.getPhone());
                return ajax;

            } else if ("sms".equals(request.getLoginType())) {
                // ==================== 短信登录 ====================
                if (StringUtils.isEmpty(request.getSmsCode())) {
                    return AjaxResult.error("验证码不能为空");
                }

                // 验证短信验证码
                String cacheKey = SMS_CODE_KEY + request.getPhone();
                String cachedCode = redisCache.getCacheObject(cacheKey);

                if (StringUtils.isEmpty(cachedCode)) {
                    return AjaxResult.error("验证码已过期，请重新获取");
                }

                if (!cachedCode.equals(request.getSmsCode())) {
                    return AjaxResult.error("验证码错误");
                }

                // 验证通过，删除缓存中的验证码
                redisCache.deleteObject(cacheKey);

                // 查询商家信息
                Merchant merchant = merchantMapper.selectMerchantByPhone(request.getPhone());
                if (merchant == null) {
                    return AjaxResult.error("账号不存在，请先注册");
                }

                // 检查是否被删除
                if (merchant.getDeletedAt() != null) {
                    return AjaxResult.error("账号已被注销");
                }

                // 检查封禁状态
                if (merchant.getStatus() == 2) {
                    return AjaxResult.error("账号已被封禁，请联系客服");
                }

                // 查询sys_user信息
                SysUser sysUser = userMapper.selectUserById(merchant.getUserId());
                if (sysUser == null) {
                    return AjaxResult.error("用户信息不存在");
                }

                // 创建LoginUser对象
                LoginUser loginUser = new LoginUser();
                loginUser.setUserId(sysUser.getUserId());
                loginUser.setDeptId(sysUser.getDeptId());
                loginUser.setUser(sysUser);

                // 使用TokenService直接生成token（跳过密码验证）
                token = tokenService.createToken(loginUser);

                // 获取商家信息
                AjaxResult merchantResult = merchantAuthService.login(request);

                // 构造返回结果
                AjaxResult ajax = AjaxResult.success("登录成功");
                ajax.put(Constants.TOKEN, token);
                ajax.put("merchantInfo", merchantResult.get("data"));

                log.info("商家短信登录成功，手机号: {}", request.getPhone());
                return ajax;

            } else {
                return AjaxResult.error("不支持的登录方式");
            }

        } catch (Exception e) {
            log.error("商家登录失败，手机号: " + request.getPhone(), e);
            return AjaxResult.error(e.getMessage());
        }
    }

    /**
     * 发送短信验证码
     */
    @PostMapping("/sms/send/{phone}")
    public AjaxResult sendSmsCode(@PathVariable String phone) {
        try {
            // 验证手机号格式
            if (!phone.matches("^1[3-9]\\d{9}$")) {
                return AjaxResult.error("手机号格式不正确");
            }

            // 检查发送频率（1分钟内只能发送1次）
            String rateLimitKey = "sms_rate_limit:" + phone;
            Long lastSendTime = redisCache.getCacheObject(rateLimitKey);

            if (lastSendTime != null) {
                return AjaxResult.error("验证码发送过于频繁，请稍后再试");
            }

            // 构建Redis缓存键
            String cacheKey = SMS_CODE_KEY + phone;

            // 检查是否已有验证码
            String cachedCode = redisCache.getCacheObject(cacheKey);
            String verifyCode;

            if (StringUtils.isNotEmpty(cachedCode)) {
                verifyCode = cachedCode;
                log.info("使用已存在的验证码，手机号: {}", phone);
            } else {
                // 生成6位数字验证码
                verifyCode = generateSixDigitCode();

                // 存入Redis，设置过期时间为5分钟
                redisCache.setCacheObject(cacheKey, verifyCode, 5, TimeUnit.MINUTES);

                log.info("生成新验证码，手机号: {}", phone);
            }

            // 发送短信
            boolean success = smsService.sendVerifyCode(phone, verifyCode, "5") != null;

            if (success) {
                // 设置发送频率限制（1分钟）
                redisCache.setCacheObject(
                        rateLimitKey,
                        System.currentTimeMillis(),
                        1,
                        TimeUnit.MINUTES
                );

                log.info("短信发送成功，手机号: {}", phone);
                return AjaxResult.success("验证码已发送，请注意查收");
            } else {
                log.error("短信发送失败，手机号: {}", phone);
                return AjaxResult.error("短信发送失败，请稍后重试");
            }

        } catch (Exception e) {
            log.error("发送短信异常，手机号: " + phone, e);
            return AjaxResult.error("短信发送失败：" + e.getMessage());
        }
    }

    /**
     * 生成6位数字验证码
     */
    private String generateSixDigitCode() {
        Random random = new Random();
        int code = random.nextInt(900000) + 100000;
        return String.valueOf(code);
    }
}
